package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zbkj.common.constants.DeviceConstants;
import com.zbkj.common.constants.ProductConstants;
import com.zbkj.common.model.agent.OrderTraceLogsRecord;
import com.zbkj.common.model.agent.OrderTraceLogsRecordItems;
import com.zbkj.common.model.order.OrderDetail;
import com.zbkj.common.model.traceable.ZfbDeviceBatchesItems;
import com.zbkj.common.model.product.Product;
import com.zbkj.common.request.*;
import com.github.pagehelper.PageHelper;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zbkj.common.exception.AppException;

import com.zbkj.common.response.ZfbDeviceBatchesPageDataResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.model.traceable.ZfbDeviceBatches;
import com.zbkj.common.utils.IdGenerator;
import com.zbkj.common.utils.SecurityUtil;
import com.zbkj.common.vo.LoginUserVo;
import com.zbkj.service.dao.device.ZfbDeviceBatchesDao;
import com.zbkj.service.service.OrderTraceLogsRecordItemsService;
import com.zbkj.service.service.OrderTraceLogsRecordService;
import com.zbkj.service.service.ZfbDeviceBatchesItemsService;
import com.zbkj.service.service.ZfbDeviceBatchesService;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
* @author dazongzi
* @description ZfbDeviceBatchesServiceImpl 接口实现
* @date 2025-06-11
*/
@Service
@Slf4j
public class ZfbDeviceBatchesServiceImpl extends ServiceImpl<ZfbDeviceBatchesDao, ZfbDeviceBatches> implements ZfbDeviceBatchesService {

    @Resource
    private ZfbDeviceBatchesDao dao;

    @Autowired
    private ZfbDeviceBatchesItemsService zfbDeviceBatchesItemsService;

    @Override
    public Boolean create(ZfbDeviceBatchesSaveRequest zfbDeviceBatchesSaveRequest) {
        checkParam(zfbDeviceBatchesSaveRequest);
        int startNum = getStartNum() + 1;

        ZfbDeviceBatches zfbDeviceBatches = new ZfbDeviceBatches();
        BeanUtils.copyProperties(zfbDeviceBatchesSaveRequest, zfbDeviceBatches, "id");
        if (ObjectUtil.isNull(zfbDeviceBatches.getType())) {
            zfbDeviceBatches.setType(1);
        }
        zfbDeviceBatches.setStatus(DeviceConstants.STATUS_GR_PROCESS);
        // 生成唯一ID，确保不重复
        Long traceId = IdGenerator.next();
        zfbDeviceBatches.setBatchesSn("T" + traceId);
        LoginUserVo loginUserVo = SecurityUtil.getLoginUserVo();
        zfbDeviceBatches.setCreateBy(loginUserVo.getUser().getRealName());
        zfbDeviceBatches.setCreateUserId(loginUserVo.getUser().getId());
        zfbDeviceBatches.setOui(DeviceConstants.OUI);
        boolean save = save(zfbDeviceBatches);
        if (!save) {
            throw new AppException(CommonResultCode.VALIDATE_FAILED, "添加失败");
        }
        Integer batchesId = zfbDeviceBatches.getId();
        // 查询出之前手动生成的mac
        List<String> macList = getManualMacList();
        // 生成指定数量的数据
        try {
            int total = zfbDeviceBatchesSaveRequest.getDeviceNum();
            int limit = 2000;
            int end = startNum + total - 1;
            Integer seq = startNum;
            int pageNum = total % limit == 0 ? total / limit : total / limit + 1;
            for (int i = 0; i < pageNum; i++) {
                List<ZfbDeviceBatchesItems> itemsList = new ArrayList<>();
                for (int j = 0; j < limit; j++) {
                    if (seq <= end) {
                        ZfbDeviceBatchesItems items = new ZfbDeviceBatchesItems();
                        items.setBatchesId(batchesId);
                        items.setStatus(DeviceConstants.ITEMS_STATUS_WAIT);
                        // 生成唯一ID，确保不重复
                        Long sn = IdGenerator.next();
                        items.setSn("BF" + sn);
                        items.setDeviceMac(genarateMac(zfbDeviceBatches.getOui(), seq));
                        if (!macList.contains(items.getDeviceMac())) {
                            itemsList.add(items);
                        } else {
                            log.warn("跳过mac地址：{}", items.getDeviceMac());
                        }
                    }
                    seq++;
                }
                if (CollUtil.isNotEmpty(itemsList)) {
                    zfbDeviceBatchesItemsService.saveBatch(itemsList);
                }
            }
            zfbDeviceBatches.setStartNum(startNum);
            zfbDeviceBatches.setEndNum(end);
            zfbDeviceBatches.setStatus(DeviceConstants.STATUS_WAIT_BAND);
            updateById(zfbDeviceBatches);
        } catch (Exception e) {
            e.printStackTrace();
            // 失败时直接删除数据
            zfbDeviceBatchesItemsService.deleteByBatchesId(batchesId);
            this.update(
                    new LambdaUpdateWrapper<ZfbDeviceBatches>()
                            .set(ZfbDeviceBatches::getStatus, 1)
                            .set(ZfbDeviceBatches::getUpdatedAt, new Date())
                            .eq(ZfbDeviceBatches::getId, batchesId)
            );
        }
        return save;
    }

    private List<String> getManualMacList() {
        return zfbDeviceBatchesItemsService.getManualMacList();
    }

    private int getStartNum() {
        LambdaQueryWrapper<ZfbDeviceBatches> checkWrapper = new LambdaQueryWrapper<>();
        checkWrapper.eq(ZfbDeviceBatches::getSource, 0);
        checkWrapper.eq(ZfbDeviceBatches::getIsDeleted, 0);
        checkWrapper.orderByDesc(ZfbDeviceBatches::getCreatedAt);
        checkWrapper.last(" limit 1");
        List<ZfbDeviceBatches> list = list(checkWrapper);
        if (CollUtil.isNotEmpty(list)) {
            return ObjectUtil.isNotNull(list.get(0).getEndNum()) ? list.get(0).getEndNum() : 0;
        }
        return 0;
    }

    private String genarateMac(String oui, Integer sequence) {
        // 将sequence转换为3字节（24位）表示
        int byte1 = (sequence >> 16) & 0xFF; // 第4字节
        int byte2 = (sequence >> 8) & 0xFF;  // 第5字节
        int byte3 = sequence & 0xFF;         // 第6字节
        return String.format("%s:%02X:%02X:%02X", oui, byte1, byte2, byte3);
    }

    private void checkParam(ZfbDeviceBatchesSaveRequest zfbDeviceBatchesSaveRequest) {

    }

    /**
     * 分页查询设备批次表
     *
     * @param request          请求参数
     * @param pageParamRequest 分页类参数
     * @return List<ZfbDeviceBatches>
     * @author dazongzi
     * @since 2025-06-11
     */
    @Override
    public List<ZfbDeviceBatchesPageDataResponse> getList(ZfbDeviceBatchesSearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        if (ObjectUtil.isNull(request.getType())) {
            request.setType(1);
        }

        //带 ZfbDeviceBatches 类的多条件查询
        LambdaQueryWrapper<ZfbDeviceBatches> lambdaQueryWrapper = Wrappers.lambdaQuery();
        if (ObjectUtil.isNotNull(request.getType())) {
            lambdaQueryWrapper.eq(ZfbDeviceBatches::getType, request.getType());
        }
        if (StrUtil.isNotBlank(request.getBatchesSn())) {
            lambdaQueryWrapper.like(ZfbDeviceBatches::getBatchesSn, URLUtil.decode(request.getBatchesSn()));
        }
        if (ObjectUtil.isNotNull(request.getStatus())) {
            lambdaQueryWrapper.eq(ZfbDeviceBatches::getStatus, request.getStatus());
        }
        lambdaQueryWrapper.eq(ZfbDeviceBatches::getType, request.getType());

        if (ObjectUtil.isNotEmpty(request.getId()) && request.getId() > 0) {
            lambdaQueryWrapper.eq(ZfbDeviceBatches::getId, request.getId());
        }
        lambdaQueryWrapper.eq(ZfbDeviceBatches::getIsDeleted, false);
        lambdaQueryWrapper.orderByDesc(ZfbDeviceBatches::getCreatedAt);
        List<ZfbDeviceBatches> activityStyles = dao.selectList(lambdaQueryWrapper);
        // 添加活动状态
        List<ZfbDeviceBatchesPageDataResponse> responses = new ArrayList<>();

        activityStyles.stream().forEach(x->{
            ZfbDeviceBatchesPageDataResponse activityStyleResponse = new ZfbDeviceBatchesPageDataResponse();
            BeanUtils.copyProperties(x, activityStyleResponse);
            responses.add(activityStyleResponse);
        });
        return responses;
    }

    @Override
    public boolean removeByIdAdmin(Integer batchesId) {
        ZfbDeviceBatches zfbDeviceBatches = getByIdException(batchesId);
        if (zfbDeviceBatches.getSource().equals(1)) {
            throw new AppException("自动生成批次不可删除");
        }
        this.update(
                new LambdaUpdateWrapper<ZfbDeviceBatches>()
                        .set(ZfbDeviceBatches::getIsDeleted, 1)
                        .set(ZfbDeviceBatches::getStatus, 1)
                        .eq(ZfbDeviceBatches::getId, batchesId)
        );
        // 删除明细
        zfbDeviceBatchesItemsService.deleteByBatchesId(batchesId);
        return true;
    }

    private ZfbDeviceBatches getByIdException(Integer jobId) {
        ZfbDeviceBatches scheduleJob = getById(jobId);
        if (ObjectUtil.isNull(scheduleJob) || BooleanUtil.isTrue(scheduleJob.getIsDeleted())) {
            throw new AppException("接收器不存在");
        }
        return scheduleJob;
    }


    @Override
    public void bindDeviceItems(Product product) {
        // 接收器（BF29）数量
        if (ObjectUtil.isNull(product.getReceiverNum())) {
            return;
        }
        List<ZfbDeviceBatches> list = getAllCanBindList();
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        int requiredStock = product.getReceiverNum(); // 需要出库的数量
        int taken = 0;
        int billsUsed = 0;
        for (ZfbDeviceBatches zfbDeviceBatches : list) {
            if (taken >= requiredStock) break;

            if (taken + zfbDeviceBatches.getUnboundNum() > requiredStock) {
                // 最后1条库存时，超过了要取出的数量
                int h = requiredStock - taken; // 剩余要取的数量
                taken += h;
                System.out.println("剩余要取的数量 = " + h + ",已取：" + taken);
                // 分批绑定到商品
                batchBindToProduct(zfbDeviceBatches, h, product.getId());
            } else {
                taken += zfbDeviceBatches.getUnboundNum();
                batchBindToProduct(zfbDeviceBatches, zfbDeviceBatches.getUnboundNum(), product.getId());
            }
            billsUsed++;
            System.out.println("取一张入库单，库存为：" + zfbDeviceBatches.getUnboundNum() + "，当前已取：" + taken);
        }
    }

    private void batchBindToProduct(ZfbDeviceBatches zfbDeviceBatches, int num, Integer linkId) {
        ZfbDeviceBatches deviceBatches = this.getById(zfbDeviceBatches.getId());
        // 按照数量取出
        List<ZfbDeviceBatchesItems> list = zfbDeviceBatchesItemsService.getListByNum(deviceBatches.getId(), num);
        Date date = new Date();
        for (ZfbDeviceBatchesItems items : list) {
            items.setLinkType(1);
            items.setLinkId(linkId);
            items.setBindTime(date);
            items.setStatus(DeviceConstants.ITEMS_STATUS_BANDED);
        }
        zfbDeviceBatchesItemsService.updateBatchById(list);
        updateDeviceBatchesStatus(deviceBatches);
    }

    /**
     * 更新设备批次状态
     * @param deviceBatches
     */
    private void updateDeviceBatchesStatus(ZfbDeviceBatches deviceBatches) {
        int unboundCount = zfbDeviceBatchesItemsService.getUnboundCount(deviceBatches.getId());
        deviceBatches.setUnboundNum(unboundCount);
        if (unboundCount == 0) {
            deviceBatches.setStatus(DeviceConstants.STATUS_ALL_BAND);
        } else {
            deviceBatches.setStatus(DeviceConstants.STATUS_PART_BAND);
        }
        this.updateById(deviceBatches);
    }

    private List<ZfbDeviceBatches> getAllCanBindList() {
        return list(new LambdaQueryWrapper<ZfbDeviceBatches>()
                .select(ZfbDeviceBatches::getId, ZfbDeviceBatches::getDeviceNum, ZfbDeviceBatches::getUnboundNum, ZfbDeviceBatches::getBadNum)
                .eq(ZfbDeviceBatches::getIsDeleted, 0)
                .gt(ZfbDeviceBatches::getUnboundNum, 0)
                .orderByAsc(ZfbDeviceBatches::getId)
        );
    }

    @Override
    public void lockDevice(Integer productId, Integer payNum, Integer userId, String orderNo) {
        // 通过商品查询出对于的设备明细，进行锁定
        List<ZfbDeviceBatchesItems> list = zfbDeviceBatchesItemsService.getWaitBindListByNum(productId, payNum);
        if (CollUtil.isEmpty(list)) {
            throw new AppException("没有蓝牙设备可用于消费");
        }
        list.stream().forEach(item -> {
            item.setUsedStatus(1);
            item.setUid(userId);
            item.setOrderNo(orderNo);
        });
        zfbDeviceBatchesItemsService.updateBatchById(list);
    }

    @Override
    public void payDeviceBatches(List<OrderDetail> orderDetailList, Integer userId) {
        Date date = new Date();
        orderDetailList.stream().forEach(orderDetail -> {
            // 认种养，锁定商品后的处理
            if (Objects.equals(orderDetail.getProductType(), ProductConstants.PRODUCT_TYPE_ADOPTING)) {
                List<ZfbDeviceBatchesItems> list = zfbDeviceBatchesItemsService.getLockListByNum(orderDetail.getProductId(), orderDetail.getOrderNo());
                if (CollUtil.isNotEmpty(list)) {
                    list.stream().forEach(x -> {
                        x.setUsedStatus(2);
                        x.setUseTime(date);
                        x.setUid(userId);
                    });
                }
                zfbDeviceBatchesItemsService.updateBatchById(list);
            }
        });
    }

}

